home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 15 / Amiga Plus Leser CD 15.iso / Tools / Development / mmu / MuManual / C_Sources / FPSPSnoop.c < prev    next >
C/C++ Source or Header  |  2002-03-12  |  15KB  |  452 lines

  1. /*************************************************
  2.  ** FPSPSnoop                                   **
  3.  ** print FPSP offending instructions out       **
  4.  **                                             **
  5.  ** Version 40.3 © 30.08.2001 Thomas Richter    **
  6.  ** THOR Software                               **
  7.  *************************************************/
  8.  
  9. /// Includes
  10. #include <exec/types.h>
  11. #include <exec/nodes.h>
  12. #include <exec/execbase.h>
  13. #include <exec/tasks.h>
  14. #include <dos/dos.h>
  15. #include <dos/dosextens.h>
  16. #include <dos/rdargs.h>
  17. #include <libraries/disassembler.h>
  18. #include <mmu/context.h>
  19. #include <thor/conversions.h>
  20.  
  21. #include <proto/exec.h>
  22. #include <proto/dos.h>
  23. #include <proto/disassembler.h>
  24. #include <proto/mmu.h>
  25.  
  26. #include <string.h>
  27. #include <stdarg.h>
  28. ///
  29. /// Defines
  30. #define LINE_F          0x2c
  31. #define OVERFLOW        0xd4
  32. #define UNDERFLOW       0xcc
  33. #define SNAN            0xd8
  34. #define OPERR           0xd0
  35. #define BUN             0xc0
  36. #define UNIMPDATA       0xdc
  37. #define INEX            0xc4
  38. #define DIVZERO         0xc8
  39. #define UNIMPEA         0xf0
  40. #define UNIMPINT        0xf4
  41.  
  42. #define NONRESIDENT     (MAPP_BLANK|MAPP_INVALID|MAPP_SWAPPED|MAPP_IO)
  43.  
  44. #define TEMPLATE        "NOFPSP/S,NOISP/S,NOOVL/S,NOUVL/S,NOSNAN/S,NOOPERR/S,NOBUN/S,NOINEX/S,NODIVZ/S,NOUNEA/S,NOUNDT/S"
  45. #define ARG_NOFPSP      0
  46. #define ARG_NOISP       1
  47. #define ARG_NOOVL       2
  48. #define ARG_NOUVL       3
  49. #define ARG_NOSNAN      4
  50. #define ARG_NOOPERR     5
  51. #define ARG_NOBUN       6
  52. #define ARG_NOINEX      7
  53. #define ARG_NODIVZ      8
  54. #define ARG_NOUNEA      9
  55. #define ARG_NOUNDT      10
  56. #define ARG_NUM         11
  57. ///
  58. /// Stuctures
  59. struct RegisterSet {
  60.         ULONG    rs_DataRegs[8];
  61.         APTR     rs_AddrRegs[7];
  62.                 APTR     rs_USP;
  63.         APTR     rs_SSP;
  64.         UWORD   *rs_PC;
  65.         UWORD    rs_SR;
  66.         UWORD    rs_Vector;
  67.         ULONG   *rs_EA;
  68.         extendedfloat rs_FPRegs[8];
  69.         ULONG    rs_FPCR;
  70.         APTR     rs_FPIAR;
  71.         ULONG    rs_FPSR;
  72. };
  73. ///
  74. /// Statics
  75. char version[]="$VER: FPSPSnoop 40.3 (30.8.2001) © THOR";
  76. struct ExecBase *SysBase;
  77. struct DosLibrary *DOSBase;
  78. struct Library *UtilityBase;
  79. struct DisassemblerBase *DisassemblerBase;
  80. struct MMUBase *MMUBase;
  81. APTR OldVectors[0x100];
  82. ///
  83. /// Externs
  84. extern APTR __asm *GetVBR(void);
  85. extern void __asm Exception_Callin(void);
  86. extern void __asm VPrintFmt(register __a0 char *fmtstring,register __a1 ULONG *stream,register __a6 struct ExecBase *SysBase);
  87. ///
  88. /// Protos
  89. LONG __saveds main(void);
  90. LONG InstallVecs(LONG *args);
  91. LONG RemoveVecs(void);
  92. void PrintFmt(char *fmtstring,...);
  93. void __asm __saveds Exception_Handler(register __a0 struct RegisterSet *);
  94. void __asm __saveds PutProc(register __d0 UBYTE c,register __a3 char **buf);
  95. void PrintFPU(extendedfloat x);
  96. BOOL IsValid(APTR addr);
  97. ///
  98.  
  99. /// main
  100. LONG __saveds main(void)
  101. {
  102. LONG rc = 25;
  103. LONG args[ARG_NUM];
  104. struct RDArgs *rd;
  105.  
  106.         SysBase = *(struct ExecBase **)(4L);
  107.         memset(args,0,sizeof(args));
  108.  
  109.         if (DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",37)) {
  110.                 if (UtilityBase = OpenLibrary("utility.library",37L)) {
  111.                         if (DisassemblerBase = (struct DisassemblerBase *)OpenLibrary("disassembler.library",40L)) {
  112.                                 if (MMUBase = (struct MMUBase *)OpenLibrary("mmu.library",40L)) {
  113.                                         if (rd = ReadArgs(TEMPLATE,args,NULL)) {
  114.  
  115.                                                 rc = InstallVecs(args);
  116.  
  117.                                                 if (rc == 0) {
  118.                                                         Wait(SIGBREAKF_CTRL_C);
  119.  
  120.                                                         RemoveVecs();
  121.                                                 }
  122.  
  123.                                                 FreeArgs(rd);
  124.                                         } else {
  125.                                                 PrintFault(IoErr(),"FPSPSnoop failed");
  126.                                                 rc = 10;
  127.                                         }
  128.  
  129.                                         CloseLibrary((struct Library *)MMUBase);
  130.                                 } else {
  131.                                         Printf("FPSPSnoop requires the mmu.library V40 or better.\n");
  132.                                 }
  133.  
  134.                                 CloseLibrary((struct Library *)DisassemblerBase);
  135.                         } else {
  136.                                 Printf("FPSPSnoop requires the disassembler.library V40 or better.\n");
  137.                         }
  138.                         CloseLibrary(UtilityBase);
  139.                 }
  140.                 CloseLibrary((struct Library *)DOSBase);
  141.         }
  142.  
  143.         return rc;
  144. }
  145. ///
  146. /// InstallVecs
  147. LONG InstallVecs(LONG *args)
  148. {
  149. APTR *vbr;
  150. APTR exh = (APTR)(&Exception_Callin);
  151.  
  152.         Disable();
  153.  
  154.         vbr = GetVBR();
  155.  
  156.         memcpy(OldVectors,vbr,0x0100 * sizeof(ULONG));
  157.  
  158.         if (!args[ARG_NOFPSP])  vbr[LINE_F>>2]          = exh;
  159.         if (!args[ARG_NOOVL])   vbr[OVERFLOW>>2]        = exh;
  160.         if (!args[ARG_NOUVL])   vbr[UNDERFLOW>>2]       = exh;
  161.         if (!args[ARG_NOSNAN])  vbr[SNAN>>2]            = exh;
  162.         if (!args[ARG_NOOPERR]) vbr[OPERR>>2]           = exh;
  163.         if (!args[ARG_NOBUN])   vbr[BUN>>2]             = exh;
  164.         if (!args[ARG_NOUNDT])  vbr[UNIMPDATA>>2]       = exh;
  165.         if (!args[ARG_NOINEX])  vbr[INEX>>2]            = exh;
  166.         if (!args[ARG_NODIVZ])  vbr[DIVZERO>>2]         = exh;
  167.         if (!args[ARG_NOUNEA])  vbr[UNIMPEA>>2]         = exh;
  168.         if (!args[ARG_NOISP])   vbr[UNIMPINT>>2]        = exh;
  169.  
  170.         Enable();
  171.  
  172.         return 0;
  173. }
  174. ///
  175. /// RemoveVecs
  176. LONG RemoveVecs(void)
  177. {
  178. APTR *vbr;
  179.  
  180.         Disable();
  181.  
  182.         vbr = GetVBR();
  183.  
  184.         memcpy(vbr,OldVectors,0x100 * sizeof(ULONG));
  185.  
  186.         Enable();
  187.  
  188.         return 0;
  189. }
  190. ///
  191. /// PrintFmt
  192. void PrintFmt(char *fmtstring,...)
  193. {
  194. va_list args;
  195.  
  196.         va_start(args,fmtstring);
  197.  
  198.         VPrintFmt(fmtstring,(ULONG *)args,SysBase);
  199.  
  200.         va_end(args);
  201. }
  202. ///
  203. /// PutProc
  204. void __asm __saveds PutProc(register __d0 UBYTE c,register __a3 char **buf)
  205. {
  206.         **buf = c;
  207.         (*buf)++;
  208.         **buf = 0;
  209. }
  210. ///
  211. /// Exception_Handler
  212. void __asm __saveds Exception_Handler(register __a0 struct RegisterSet *rs)
  213. {
  214. BOOL dumpfpu = TRUE;
  215. char sr[16],buffer[82],*bufptr;
  216. char *name;
  217. struct DisData ds;
  218.  
  219.         Disable();
  220.  
  221.         PrintFmt("Caught 68040/68060 trap conditition: ");
  222.  
  223.         switch(rs->rs_Vector) {
  224.                 case LINE_F:
  225.                         PrintFmt("Unimplemented FPU instruction ");
  226.                         break;
  227.                 case OVERFLOW:
  228.                         PrintFmt("Overflow ");
  229.                         break;
  230.                 case UNDERFLOW:
  231.                         PrintFmt("Underflow ");
  232.                         break;
  233.                 case SNAN:
  234.                         PrintFmt("Signalling NAN ");
  235.                         break;
  236.                 case OPERR:
  237.                         PrintFmt("Operand Error ");
  238.                         break;
  239.                 case BUN:
  240.                         PrintFmt("Branch Unordered ");
  241.                         break;
  242.                 case UNIMPDATA:
  243.                         PrintFmt("Unimplemented FPU data type ");
  244.                         break;
  245.                 case INEX:
  246.                         PrintFmt("Inexact Result ");
  247.                         break;
  248.                 case DIVZERO:
  249.                         PrintFmt("FPU Divide by Zero ");
  250.                         break;
  251.                 case UNIMPEA:
  252.                         PrintFmt("Unimplemented EA ");
  253.                         break;
  254.                 case UNIMPINT:
  255.                         PrintFmt("Unimplemented integer instruction ");
  256.                         dumpfpu = FALSE;
  257.                         break;
  258.                 default:
  259.                         PrintFmt("Unexpected exception ");
  260.         }
  261.         PrintFmt("\n");
  262.  
  263.         /* Fill in the SR */
  264.         sr[0]  = (rs->rs_SR & 0x8000)?('T'):('_');
  265.         sr[1]  = (rs->rs_SR & 0x4000)?('t'):('_');
  266.         sr[2]  = (rs->rs_SR & 0x2000)?('S'):('_');
  267.         sr[3]  = (rs->rs_SR & 0x1000)?('M'):('_');
  268.         sr[4]  = ((rs->rs_SR & 0x0700)>>8) | '0';
  269.         sr[5]  = (rs->rs_SR & 0x10)?('X'):('_');
  270.         sr[6]  = (rs->rs_SR & 0x08)?('N'):('_');
  271.         sr[7]  = (rs->rs_SR & 0x04)?('Z'):('_');
  272.         sr[8]  = (rs->rs_SR & 0x02)?('V'):('_');
  273.         sr[9] = (rs->rs_SR & 0x01)?('C'):('_');
  274.         sr[10] = 0;
  275.  
  276.         if (rs->rs_SR & 0x0700) {
  277.                 name = "Autovector Interrupt";
  278.         } else {
  279.                 name = SysBase->ThisTask->tc_Node.ln_Name;
  280.                 if (!IsValid(name)) {
  281.                         name = "????";
  282.                 }
  283.                 if (SysBase->ThisTask->tc_Node.ln_Type == NT_PROCESS) {
  284.                         struct Process *proc;
  285.                         proc = (struct Process *)(SysBase->ThisTask);
  286.  
  287.                         if (proc->pr_CLI) {
  288.                                 struct CommandLineInterface *cli;
  289.  
  290.                                 cli = (struct CommandLineInterface *)BADDR(proc->pr_CLI);
  291.  
  292.                                 if (IsValid(cli)) {
  293.                                         if (cli->cli_CommandName) {
  294.                                                 char *modname;
  295.                                                 modname = (char *)BADDR(cli->cli_CommandName);
  296.                                                 if (IsValid(modname) && (*modname)) {
  297.                                                         name = modname+1;
  298.                                                 }
  299.                                         }
  300.                                 }
  301.                         }
  302.                 }
  303.         }
  304.  
  305.  
  306.         PrintFmt("PC   : %x SR: %s USP: %x SSP: %x EA: %x (%c)(%c)\n"
  307.                  "Name : %s\n",rs->rs_PC,sr,rs->rs_USP,rs->rs_SSP,rs->rs_EA,
  308.                   (SysBase->IDNestCnt == -1)?(' '):('I'),
  309.                   (SysBase->TDNestCnt == -1)?(' '):('T'),
  310.                   name);
  311.  
  312.         PrintFmt("Data : %x %x %x %x %x %x %x %x\n",
  313.                 rs->rs_DataRegs[0],rs->rs_DataRegs[1],rs->rs_DataRegs[2],rs->rs_DataRegs[3],
  314.                 rs->rs_DataRegs[4],rs->rs_DataRegs[5],rs->rs_DataRegs[6],rs->rs_DataRegs[7]);
  315.         PrintFmt("Addr : %x %x %x %x %x %x %x %x\n",
  316.                 rs->rs_AddrRegs[0],rs->rs_AddrRegs[1],rs->rs_AddrRegs[2],rs->rs_AddrRegs[3],
  317.                 rs->rs_AddrRegs[4],rs->rs_AddrRegs[5],rs->rs_AddrRegs[6],
  318.                 (rs->rs_SR & 0x2000)?(rs->rs_SSP):(rs->rs_USP));
  319.  
  320.         if (rs->rs_EA) {
  321.                 if (IsValid(rs->rs_EA)) {
  322.                         PrintFmt("EA   : %x %x %x %x %x %x %x %x\n",
  323.                                  rs->rs_EA[0],rs->rs_EA[1],rs->rs_EA[2],rs->rs_EA[3],
  324.                                  rs->rs_EA[4],rs->rs_EA[5],rs->rs_EA[6],rs->rs_EA[7]);
  325.                 }
  326.         }
  327.  
  328.         if (dumpfpu) {
  329.                 int i;
  330.                 for (i = 0;i<8;i++) {
  331.                         PrintFmt("FP%c  : ",i+'0');
  332.                         PrintFPU((rs->rs_FPRegs[i]));
  333.                 }
  334.  
  335.                 sr[0] = (rs->rs_FPCR & 0x8000)?('B'):('_');
  336.                 sr[1] = (rs->rs_FPCR & 0x4000)?('S'):('_');
  337.                 sr[2] = (rs->rs_FPCR & 0x2000)?('P'):('_');
  338.                 sr[3] = (rs->rs_FPCR & 0x1000)?('O'):('_');
  339.                 sr[4] = (rs->rs_FPCR & 0x0800)?('U'):('_');
  340.                 sr[5] = (rs->rs_FPCR & 0x0400)?('D'):('_');
  341.                 sr[6] = (rs->rs_FPCR & 0x0200)?('2'):('_');
  342.                 sr[7] = (rs->rs_FPCR & 0x0100)?('1'):('_');
  343.                 sr[8] = '.';
  344.                 switch (rs->rs_FPCR & 0xc0) {
  345.                         case 0x00:
  346.                                 sr[9] = 'n';
  347.                                 break;
  348.                         case 0x40:
  349.                                 sr[9] = '0';
  350.                                 break;
  351.                         case 0x80:
  352.                                 sr[9] = '-';
  353.                                 break;
  354.                         case 0xc0:
  355.                                 sr[9] = '+';
  356.                                 break;
  357.                 }
  358.                 switch (rs->rs_FPCR & 0x30) {
  359.                         case 0x00:
  360.                                 sr[10] = 'x';
  361.                                 break;
  362.                         case 0x10:
  363.                                 sr[10] = 's';
  364.                                 break;
  365.                         case 0x20:
  366.                                 sr[10] = 'd';
  367.                                 break;
  368.                         case 0x30:
  369.                                 sr[10] = '?';
  370.                                 break;
  371.                 }
  372.                 sr[11] = 0;
  373.  
  374.                 PrintFmt("FPCR : %s ",sr);
  375.  
  376.                 sr[0] = (rs->rs_FPSR & (1<<27))?('N'):('_');
  377.                 sr[1] = (rs->rs_FPSR & (1<<26))?('Z'):('_');
  378.                 sr[2] = (rs->rs_FPSR & (1<<25))?('I'):('_');
  379.                 sr[3] = (rs->rs_FPSR & (1<<24))?('U'):('_');
  380.                 sr[4] = 0;
  381.  
  382.                 PrintFmt("FPSR : %s.%c%x",sr,(rs->rs_FPSR & (1<<23))?('-'):('+'),(rs->rs_FPSR >> 16) & 0x7f);
  383.  
  384.                 sr[0] = (rs->rs_FPSR & 0x8000)?('B'):('_');
  385.                 sr[1] = (rs->rs_FPSR & 0x4000)?('S'):('_');
  386.                 sr[2] = (rs->rs_FPSR & 0x2000)?('P'):('_');
  387.                 sr[3] = (rs->rs_FPSR & 0x1000)?('O'):('_');
  388.                 sr[4] = (rs->rs_FPSR & 0x0800)?('U'):('_');
  389.                 sr[5] = (rs->rs_FPSR & 0x0400)?('D'):('_');
  390.                 sr[6] = (rs->rs_FPSR & 0x0200)?('2'):('_');
  391.                 sr[7] = (rs->rs_FPSR & 0x0100)?('1'):('_');
  392.                 sr[8] = '.';
  393.                 sr[9] = (rs->rs_FPSR & 0x80)?('v'):('_');
  394.                 sr[10] = (rs->rs_FPSR & 0x40)?('o'):('_');
  395.                 sr[11] = (rs->rs_FPSR & 0x20)?('u'):('_');
  396.                 sr[12] = (rs->rs_FPSR & 0x10)?('d'):('_');
  397.                 sr[13] = (rs->rs_FPSR & 0x08)?('i'):('_');
  398.                 sr[14] = 0;
  399.  
  400.                 PrintFmt(" %s FPIAR : %x\n\n",sr,rs->rs_FPIAR);
  401.         }
  402.  
  403.         bufptr         = buffer;
  404.         ds.ds_From     = rs->rs_PC;
  405.         ds.ds_UpTo     = rs->rs_PC+1;
  406.         ds.ds_PC       = rs->rs_PC;
  407.         ds.ds_PutProc  = (void *)(&PutProc);
  408.         ds.ds_UserData = &bufptr;
  409.         ds.ds_UserBase = NULL;
  410.         ds.ds_Truncate = 80;
  411.         ds.ds_reserved = 0;
  412.  
  413.         Disassemble(&ds);
  414.  
  415.         PrintFmt("%s\n",buffer);
  416.  
  417.         Enable();
  418. }
  419. ///
  420. /// PrintFPU
  421. void PrintFPU(extendedfloat x)
  422. {
  423. char out[32];
  424.  
  425.         XToA(x,out);
  426.  
  427.         PrintFmt("%x%x%x = %s\n",x[0],x[1],x[2],out);
  428. }
  429. ///
  430. /// IsValid
  431. BOOL IsValid(APTR addr)
  432. {
  433. struct MMUContext *ctx;
  434. ULONG  prop;
  435.  
  436.         ctx = CurrentContext(NULL);
  437.         ctx = SuperContext(ctx);
  438.  
  439.         prop = GetPageProperties(ctx,(ULONG)addr,TAG_DONE);
  440.  
  441.         if (prop & NONRESIDENT)
  442.                 return FALSE;
  443.  
  444.         prop = GetPageProperties(ctx,(ULONG)(addr) + 0x20,TAG_DONE);
  445.  
  446.         if (prop & NONRESIDENT)
  447.                 return FALSE;
  448.  
  449.         return TRUE;
  450. }
  451. ///
  452.